package com.xuecheng.api.config;

import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;

/**
 * @author 勾新杰
 * @version 1.0
 * @description 多文件上传支持配置，应用于单独client的配置，对应client用@FeignClient("configuration = MultipartSupportConfig")可以指定这个配置
 * @date 2022/10/15 22:13
 */
@Slf4j
@Configuration
@RequiredArgsConstructor
public class MultipartSupportConfig {

    /**
     * 配置文件转换器
     */
    private final ObjectFactory<HttpMessageConverters> messageConverters;

    /**
     * feign文件上传配置
     *
     * @return Encoder
     */
    @Bean
    @Primary // 注入相同类型的bean时优先使用
    @Scope("prototype") // 每次请求都会创建一个新的实例
    public Encoder feignEncoder() {
        return new SpringFormEncoder(new SpringEncoder(messageConverters));
    }

    /**
     * 将文件转换成MultipartFile
     *
     * @param file 原始文件
     * @return 转换后的文件MultipartFile
     */
    public static MultipartFile getMultipartFile(File file) {
        // 构建MultipartFile表单上传的<input type="file" name="file">
        FileItem item = new DiskFileItemFactory().createItem("filedata", MediaType.MULTIPART_FORM_DATA_VALUE, true, file.getName());
        try (FileInputStream inputStream = new FileInputStream(file);
             OutputStream outputStream = item.getOutputStream()) {
            IOUtils.copy(inputStream, outputStream);
        } catch (Exception e) {
            log.error("文件转换成MultipartFile失败，原因为{}", e.getMessage());
            return null;
        }
        return new CommonsMultipartFile(item);
    }
}
